﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;

namespace LS.Common
{
   public static class UtilsHelper
    {
       public static int GetStrLength(string str)
        {
            if (str == null)
            {
                return 0;
            }
            return System.Text.Encoding.Default.GetBytes(str).Length;
        }

        public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            HashSet<TKey> seenKeys = new HashSet<TKey>();
            foreach (TSource element in source)
            {
                if (seenKeys.Add(keySelector(element)))

                {
                    yield return element;
                }
            }
        }


        public static bool StringToBool(string str)
        {

            bool isResult = false;

            bool.TryParse(str, out isResult);

            return isResult;
        }

        #region 去除字符串中所有空格

        /// <summary>
        /// 去除字符串中所有空格
        /// </summary>
        /// <param name="strTmp"></param>
        public static string TrimBlank(string strTmp)
        {
            string newstr = string.Empty;
            CharEnumerator ce = strTmp.Trim().GetEnumerator();
            byte[] array = new byte[1];
            int asciicode = 0;
            while (ce.MoveNext())
            {
                array = System.Text.Encoding.ASCII.GetBytes(ce.Current.ToString());
                asciicode = (short)(array[0]);
                if (asciicode != 32)
                    newstr += ce.Current.ToString();
            }
            return newstr;
        }

        #endregion

        #region 数字转换

        public static string GetChineseNum(string p_num)
        {
            return NumToChn(p_num);
        }

        //字符串转数字
        public static int GetIntByStr(string str, int defaultNum = 0)
        {
            int num = defaultNum;
            int.TryParse(str, out num);
            return num;
        }

        //转换数字
        private static char CharToNum(char x)
        {
            string stringChnNames = "零一二三四五六七八九";
            string stringNumNames = "0123456789";
            return stringChnNames[stringNumNames.IndexOf(x)];
        }

        //转换万以下整数
        private static string WanStrToInt(string x)
        {
            string[] stringArrayLevelNames = new string[4] { "", "十", "百", "千" };
            string ret = "";
            int i;
            for (i = x.Length - 1; i >= 0; i--)
                if (x[i] == '0')
                {
                    ret = CharToNum(x[i]) + ret;
                }
                else
                {
                    ret = CharToNum(x[i]) + stringArrayLevelNames[x.Length - 1 - i] + ret;
                }
            while ((i = ret.IndexOf("零零")) != -1)
            {
                ret = ret.Remove(i, 1);
            }
            if (ret[ret.Length - 1] == '零' && ret.Length > 1)
            {
                ret = ret.Remove(ret.Length - 1, 1);
            }
            if (ret.Length >= 2 && ret.Substring(0, 2) == "一十")
            {
                ret = ret.Remove(0, 1);
            }
            return ret;
        }

        //转换整数
        private static string StrToInt(string x)
        {
            int len = x.Length;
            string ret, temp;
            if (len <= 4)
            {
                ret = WanStrToInt(x);
            }
            else if (len <= 8)
            {
                ret = WanStrToInt(x.Substring(0, len - 4)) + "万";
                temp = WanStrToInt(x.Substring(len - 4, 4));
                if (temp.IndexOf("千") == -1 && temp != "")
                    ret += "零" + temp;
                else
                    ret += temp;
            }
            else
            {
                ret = WanStrToInt(x.Substring(0, len - 8)) + "亿";
                temp = WanStrToInt(x.Substring(len - 8, 4));
                if (temp.IndexOf("千") == -1 && temp != "")
                {
                    ret += "零" + temp;
                }
                else
                {
                    ret += temp;
                }
                ret += "万";
                temp = WanStrToInt(x.Substring(len - 4, 4));
                if (temp.IndexOf("千") == -1 && temp != "")
                {
                    ret += "零" + temp;
                }
                else
                {
                    ret += temp;
                }
            }
            int i;
            if ((i = ret.IndexOf("零万")) != -1)
            {
                ret = ret.Remove(i + 1, 1);
            }
            while ((i = ret.IndexOf("零零")) != -1)
            {
                ret = ret.Remove(i, 1);
            }
            if (ret[ret.Length - 1] == '零' && ret.Length > 1)
            {
                ret = ret.Remove(ret.Length - 1, 1);
            }
            return ret;
        }

        //转换小数
        private static string StrToDouble(string x)
        {
            string ret = "";
            for (int i = 0; i < x.Length; i++)
            {
                ret += CharToNum(x[i]);
            }
            return ret;
        }

        private static string NumToChn(string x)
        {
            if (x.Length == 0)
            {
                return "";
            }
            string ret = "";
            if (x[0] == '-')
            {
                ret = "负";
                x = x.Remove(0, 1);
            }
            if (x[0].ToString() == ".")
            {
                x = "0" + x;
            }
            if (x[x.Length - 1].ToString() == ".")
            {
                x = x.Remove(x.Length - 1, 1);
            }
            if (x.IndexOf(".") > -1)
            {
                ret += StrToInt(x.Substring(0, x.IndexOf("."))) + "点" + StrToDouble(x.Substring(x.IndexOf(".") + 1));
            }
            else
            {
                ret += StrToInt(x);
            }
            return ret;
        }

        #endregion

        #region 去除HTML标签

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Input"></param>
        /// <returns></returns>
        public static string RemoveSpaceHtmlTag(string Input)
        {
            string input = Input;
            //去html标签
            input = Regex.Replace(input, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"-->", "", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"<!--.*", "", RegexOptions.IgnoreCase);

            input = Regex.Replace(input, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(nbsp|#160);", " ", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(iexcl|#161);", "\xa1", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(cent|#162);", "\xa2", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(pound|#163);", "\xa3", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(copy|#169);", "\xa9", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&#(\d+);", "", RegexOptions.IgnoreCase);

            input.Replace("<", "");
            input.Replace(">", "");
            input.Replace("\r\n", "");
            input = Regex.Replace(input.Trim(), "\\s+", " ");
            return input;
        }


        public static string RemoveSpaceHtmlTagNoImg(string Input)
        {
            string input = Input;
            //去html标签
            input = Regex.Replace(input, @"<(?!\/?br\/?.+?>|\/?img.+?>|\/?p.+?)[^<>]*>", "", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"\sstyle=""(?<style>([^"";]+;?)+)""", "", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"-->", "", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"<!--.*", "", RegexOptions.IgnoreCase);

            input = Regex.Replace(input, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(nbsp|#160);", " ", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(iexcl|#161);", "\xa1", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(cent|#162);", "\xa2", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(pound|#163);", "\xa3", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&(copy|#169);", "\xa9", RegexOptions.IgnoreCase);
            input = Regex.Replace(input, @"&#(\d+);", "", RegexOptions.IgnoreCase);

            input.Replace("<", "");
            input.Replace(">", "");
            //input.Replace("\r\n", "");
            //input = Regex.Replace(input.Trim(), "\\s+", " ");
            return input;
        }

        public static string GetFullText(string HtmlSource)
        {

            string input = HtmlSource;
            input = new Regex(@"(?m)<script[^>]*>(\w|\W)*?</script[^>]*>", RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(input, "");
            input = new Regex(@"(?m)<style[^>]*>(\w|\W)*?</style[^>]*>", RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(input, "");
            input = new Regex(@"(?m)<select[^>]*>(\w|\W)*?</select[^>]*>", RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(input, "");
            input = new Regex("(<[^>]+?>)|&nbsp;", RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(input, "");
            Regex regex3 = new Regex(@"(\s)+", RegexOptions.Multiline | RegexOptions.IgnoreCase);
            return HttpUtility.HtmlDecode(regex3.Replace(input, " ")).Trim();
        }
        public static string GetText(string HtmlSource)
        {
            HtmlSource = Regex.Replace(HtmlSource, "<[^/pbr][^>]*.|</[^pbr][^>]*.", @"\r\n", RegexOptions.Multiline | RegexOptions.IgnoreCase);
            HtmlSource = GetFullText(HtmlSource);
            return HtmlSource;
        }



        #endregion

        #region  URLEncode编码解码
        /// <summary>
        /// 对字符进行UrlEncode编码
        /// string转Encoding格式
        /// </summary>
        /// <param name="text"></param>
        /// <param name="encod">编码格式</param>
        /// <param name="cap">是否输出大写字母</param>
        /// <returns></returns>
        public static string UrlEncode(string text, Encoding encod, bool cap = false)
        {
            if (cap)
            {
                StringBuilder builder = new StringBuilder();
                foreach (char c in text)
                {
                    if (System.Web.HttpUtility.UrlEncode(c.ToString(), encod).Length > 1)
                    {
                        builder.Append(System.Web.HttpUtility.UrlEncode(c.ToString(), encod).ToUpper());
                    }
                    else
                    {
                        builder.Append(c);
                    }
                }
                return builder.ToString();
            }
            else
            {
                string encodString = System.Web.HttpUtility.UrlEncode(text, encod);
                return encodString;
            }
        }

        /// <summary>
        /// 对字符进行UrlDecode解码
        /// Encoding转string格式
        /// </summary>
        /// <param name="encodString"></param>
        /// <param name="encod">编码格式</param>
        /// <returns></returns>
        public static string UrlDecode(string encodString, Encoding encod)
        {
            string text = System.Web.HttpUtility.UrlDecode(encodString, encod);
            return text;
        }
        #endregion

        #region 时间戳和datetime转换
        /// <summary>
        /// DateTime转时间戳
        /// </summary>
        /// <param name="time">DateTime时间</param>
        /// <param name="type">0为毫秒,1为秒</param>
        /// <returns></returns>
        public static double ConvertTimestamp(DateTime time, int type = 0)
        {
            double intResult = 0;
            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            if (type == 0)
            {
                intResult = (time - startTime).TotalMilliseconds;
            }
            else if (type == 1)
            {
                intResult = (time - startTime).TotalSeconds;
            }
            else
            {
                Console.WriteLine("参数错误!");
            }
            return Math.Round(intResult, 0);
        }

        #endregion

        #region  对象和byte数组转换

        /// <summary>
        /// 将对象转换为byte数组
        /// </summary>
        /// <param name="obj">被转换对象</param>
        /// <returns>转换后byte数组</returns>
        public static byte[] Object2Bytes(object obj)
        {
            byte[] buff;
            using (MemoryStream ms = new MemoryStream())
            {
                IFormatter iFormatter = new BinaryFormatter();
                iFormatter.Serialize(ms, obj);
                buff = ms.GetBuffer();
            }
            return buff;
        }

        /// <summary>
        /// 将byte数组转换成对象
        /// </summary>
        /// <param name="buff">被转换byte数组</param>
        /// <returns>转换完成后的对象</returns>
        public static object Bytes2Object(byte[] buff)
        {
            object obj;
            using (MemoryStream ms = new MemoryStream(buff))
            {
                IFormatter iFormatter = new BinaryFormatter();
                obj = iFormatter.Deserialize(ms);
            }
            return obj;
        }

        #endregion
        #region base64和图片相互转换
        /// <summary>
        /// 将Base64字符串转换为图片并保存到本地
        /// </summary>
        /// <param name="base64Str">base64字符串</param>
        /// <param name="savePath">图片保存地址，如：/Content/Images/10000.png</param>
        /// <returns></returns>
        public static bool Base64StrToImage(string base64Str, string savePath)
        {
            var ret = true;
            try
            {
                base64Str = base64Str.Replace("data:image/png;base64,", "").Replace("data:image/jgp;base64,", "")
                    .Replace("data:image/jpg;base64,", "").Replace("data:image/jpeg;base64,", ""); //将base64头部信息替换
                var bitmap = GetImageFromBase64(base64Str);
                if (bitmap != null)
                {
                    //创建文件夹
                    var folderPath = savePath.Substring(0, savePath.LastIndexOf('\\'));
                    ////FileHelper.CreateDir(folderPath);
                    if (!Directory.Exists(folderPath))
                    {
                        Directory.CreateDirectory(folderPath);
                    }
                    //图片后缀格式
                    var suffix = savePath.Substring(savePath.LastIndexOf('.') + 1,
                        savePath.Length - savePath.LastIndexOf('.') - 1).ToLower();
                    var suffixName = suffix == "png"
                        ? ImageFormat.Png
                        : suffix == "jpg" || suffix == "jpeg"
                            ? ImageFormat.Jpeg
                            : suffix == "bmp"
                                ? ImageFormat.Bmp
                                : suffix == "gif"
                                    ? ImageFormat.Gif
                                    : ImageFormat.Jpeg;

                    //这里复制一份对图像进行保存，否则会出现“GDI+ 中发生一般性错误”的错误提示
                    var bmpNew = new Bitmap(bitmap);
                    bmpNew.Save(savePath, suffixName);
                    bmpNew.Dispose();
                    bitmap.Dispose();
                }
                else
                {
                    ret = false;
                }
            }
            catch 
            {
                ret = false;
            }
            return ret;

        }

        /// <summary>
        /// 获取base64位图片的后缀
        /// </summary>
        /// <param name="base64Str"></param>
        /// <returns></returns>
        public static string GetBase64Sufix(string base64Str)
        {
            string sufix = ".";
            try
            {
                int startIndex = base64Str.IndexOf("/");
                int endIndex = base64Str.IndexOf(";") - 1;
                sufix += base64Str.Substring(startIndex + 1, endIndex - startIndex);
            }
            catch 
            {

            }
            return sufix;
        }

        /// <summary>
        /// 获得base64图片头部分
        /// </summary>
        /// <param name="sufix"></param>
        /// <returns></returns>
        public static string GetBase64Prefix(string sufix)
        {
            return $"data:image/{sufix};base64,";
        }

        /// <summary>
        /// Image 转成 base64
        /// </summary>
        /// <param name="fileFullName"></param>
        public static string ImageToBase64(string fileFullName)
        {
            try
            {
                Bitmap bmp = new Bitmap(fileFullName);
                MemoryStream ms = new MemoryStream();
                var suffix = fileFullName.Substring(fileFullName.LastIndexOf('.') + 1,
                    fileFullName.Length - fileFullName.LastIndexOf('.') - 1).ToLower();
                var suffixName = suffix == "png"
                    ? ImageFormat.Png
                    : suffix == "jpg" || suffix == "jpeg"
                        ? ImageFormat.Jpeg
                        : suffix == "bmp"
                            ? ImageFormat.Bmp
                            : suffix == "gif"
                                ? ImageFormat.Gif
                                : ImageFormat.Jpeg;

                bmp.Save(ms, suffixName);
                byte[] arr = new byte[ms.Length]; ms.Position = 0;
                ms.Read(arr, 0, (int)ms.Length); ms.Close();
                string prefix = GetBase64Prefix(suffix);
                return prefix + Convert.ToBase64String(arr);
            }
            catch 
            {
                return null;
            }

        }
        public static Bitmap GetImageFromBase64(string base64string)
        {
            byte[] b = Convert.FromBase64String(base64string);
            MemoryStream ms = new MemoryStream(b);
            Bitmap bitmap = new Bitmap(ms);
            return bitmap;
        }
        #endregion
    }
}
